package com.xrui.hbaseview.reflection;



import com.xrui.hbaseview.io.PathHelper;

import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;

/**
 * This class is responsible for compiling java code.
 */
public class JavaCompiler {

    //region Variables
    private static List<String> errors;
    //endregion

    //region Constructor
    static {
        errors = new ArrayList<>();
    }

    private JavaCompiler() {
    }
    //endregion

    //region Public Properties
    public static List<String> getErrors() {
        return errors;
    }
    //endregion

    //region Public Methods
    public static boolean compile(File sourceCode, String outputFolder) throws Exception {
        errors.clear();

        // make sure all directories are created.
        new File(outputFolder).mkdirs();

        StandardJavaFileManager fileManager = null;

        try {
            javax.tools.JavaCompiler compiler = (javax.tools.JavaCompiler) Class.forName("com.sun.tools.javac.api.JavacTool").getConstructor().newInstance();
            fileManager = compiler.getStandardFileManager(null, null, null);

            DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
            Iterable<? extends JavaFileObject> units = fileManager.getJavaFileObjectsFromFiles(Collections.singletonList(sourceCode));

            Collection<String> options = new ArrayList<>();
            options.addAll(Arrays.asList("-classpath", System.getProperty("java.class.path"), "-d", outputFolder));

            boolean success = compiler.getTask(null, fileManager, diagnostics, options, null, units).call();
            if (!success) {
                for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
                    errors.add(diagnostic.getMessage(Locale.ENGLISH));
                }
            }

            return success;
        } finally {
            if (fileManager != null) {
                fileManager.close();
            }
        }
    }

    public static File saveCode(String className, String code, String outputFolder) throws IOException {
        // make sure all directories are created.
        new File(outputFolder).mkdirs();

        String path = PathHelper.append(outputFolder, className + ".java");
        File file = new File(path);

        FileOutputStream stream = null;

        try {
            stream = new FileOutputStream(file);
            stream.write(code.getBytes());

            return file;
        } finally {
            if (stream != null) {
                stream.close();
            }
        }
    }
    //endregion
}
